<!--
 * @Author: lsjweiyi lsjweiyi
 * @Date: 2023-04-09 15:55:11
 * @LastEditors: lsjweiyi 759209794@qq.com
 * @LastEditTime: 2024-05-15 22:00:59
 * @FilePath: \web-ssg\pages\image\IdcardChangeColor.vue
 * @Description: 证件照换底色
-->
<template>
    <div class="title">{{ toolIMsg.name }}</div>
    <div class="myBody">
        <span>请选择背景色：</span>
        <div style="display: inline-flex; align-items: center; ">
            <!-- 颜色选择组 -->
            <div class="custom-radios">
                <n-tooltip trigger="hover">
                    <template #trigger>
                        <div>
                            <input type="radio" id="color-0" name="color" value="touming" checked
                                @input="getSelectRGB('touming')" />
                            <label for="color-0">
                                <span>
                                    <img src="/images/transparent.png"
                                        style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%" />
                                </span>
                            </label>
                        </div>
                    </template>
                    该选项是背景透明，但只能返回为png格式！
                </n-tooltip>
                <!-- 最后一个颜色是自定义颜色,默认是不显示的,只有选了颜色且跟前三个不相同时才显示 -->
                <div v-for="(color, index) in colorList" v-show="index < colorList.length - 1 || colorLastShow()">
                    <input type="radio" :id="'color-' + (index + 1)" name="color" :value="color"
                        @input="getSelectRGB(color)" />
                    <label :for="'color-' + (index + 1)">
                        <span :style="{ 'background-color': color }"> </span>
                    </label>
                </div>
            </div>
            <n-button @click="colorpickShow" id="colorpickButton">其他颜色</n-button>
            <input type="color" id="customColor" style="visibility: hidden; width: 0; height: 0"
                @input="customColorPick" />
        </div>
        <div id="bottomImg" class="bottomImg"
            :style="{ height: imgHeigth, width: imgWidth, backgroundImage: 'url(' + upLoadImg + ')', margin: '10px' }">
            <span v-if="!showTouming" class="imgLabel">原图</span>
            <div v-if="showTouming" class="upperImg touming"></div>
            <div v-if="newImgURL" class="upperImg"
                :style="{ backgroundImage: 'url(' + newImgURL + ')', width: 100 - upperImgWidth + '%' }">
                <span class="imgLabel">结果图</span>
            </div>
            <div v-else class="upperUndefined" :style="{ width: 100 - upperImgWidth + '%' }">
                <span class="undefinedSpan">暂无结果</span>
            </div>
            <span v-if="!showTouming" class="spanHandle"
                :style="{ left: 'calc(' + upperImgWidth + '% - 24px)' }"></span>
            <input v-if="!showTouming" class="inputRange" type="range" v-model="upperImgWidth" min="0" max="100" />
        </div>
        <div class="buttonGroup">
            <div style="display: inline-flex;width: 100%;">
                <SingleFileUpload @select-file="fileChange" @upload-file="myUpload" :loading="loading"
                    style="font-size: 96px" :disabled="!colorChange">
                </SingleFileUpload>
            </div>
            <div style="display: inline-flex;width: 100%;"> <pay-and-down v-model:task-id="taskId"
                    :tool-name="toolIMsg.name" :tool-id="toolIMsg.toolId"></pay-and-down>
                <HistoryDown :tool-name="toolIMsg.name" :tool-id="toolIMsg.toolId"></HistoryDown>
            </div>
        </div>
        <div class="insideCard">
            <div style="color: red; margin-bottom: 10px">支持格式：jpg/jpeg、png、bmp</div>
            <div style="color: red; margin-bottom: 10px">{{ "限制大小：" + maxSize + "KB" }}</div>
            <div>{{ toolIMsg.description }}</div>
            <div style="font-size: 16px; margin-top: 10px">PS：本站不收集任何个人信息，请放心使用！上传的图片在服务器约保存24小时后自动删除</div>
        </div>
    </div>
</template>
<script lang="ts" setup>
import "@/assets/insideBody.scss";
import "@/assets/twoImgCompare.scss";
const toolIMsg = getImageMenuItem("idcardChangeColor");
const maxSize = 3070; // 上传图片限制的大小，单位KB
useHead({
    title: toolIMsg.name,
});
useSeoMeta({
    description: toolIMsg.description,
});
let imgBase = { color: { b: 0, g: 0, r: 255 } } as IChangebgColor;
const taskId = ref("");
const upLoadImg = ref<string | undefined>("/images/region1.jpg");
const newImgURL = ref<string | undefined>("/images/changeBgColor1.jpg");

const upperImgWidth = ref(50); // 滑块的值，用于控制结果图的宽度，默认50%，注意0才是完全展示

const showTouming = ref(false); // 当用户选择透明背景，且结果已出来时，才展示
const loading = ref(false);
const colorChange = ref(false)
// 自定义上传图像的方法覆盖默认方法
const myUpload = (file: File) => {
    loading.value = true; // 设置loading状态，防止重复点击上传按钮
    colorChange.value = false
    // 后端接口
    cardChangeBackground(imgBase, toolIMsg.toolId as number).then((res) => {
        if (responseDeal(res, "证件照换底色失败！", taskId, undefined, newImgURL)) {
            if (imgBase.color == undefined) {
                showTouming.value = true; // 展示透明背景
                upperImgWidth.value = 0; // 结果图铺满整个区域，滑块的值设为100%
            }
        }
        loading.value = false; // 取消loading状态
    });
};

const imgHeigth = ref("439px"); // 记录原始图片的宽高
const imgWidth = ref("439px");
/**
 * @description: 上传文件按钮回调函数
 * @param {*} file
 * @return {*}
 */
const fileChange = (file: File, fn: (result: boolean) => void) => {
    checkFile(file, maxSize, [50, 4096]).then((res) => {
        if (res) {
            showTouming.value = false; // 重置透明背景的展示状态，防止用户选择其他颜色时，结果图展示的是透明背景
            imgBase.file = file;
            upLoadImg.value = res.base64;
            newImgURL.value = undefined;
            fn(true);
            taskId.value = ""
            getImgSize(res.width, res.height);
        } else {
            fn(false);
        }
    });
};

function getImgSize(width: number, height: number) {
    // 防止图片太小影响观感，图片高度小于300px放大到300px
    let fangDaXiShu = 1;
    if (height < 100) {
        fangDaXiShu = 100 / height;
    }
    let newImgWidth = width * fangDaXiShu;
    let newImgHeight = height * fangDaXiShu;
    let kuangDubi = Math.min(maxWidth / newImgWidth, 1);
    let gaoDubi = Math.min(maxHeight / newImgHeight, 1);


    if (kuangDubi <= gaoDubi) {
        imgWidth.value = newImgWidth * kuangDubi + "px"; //限制宽度为最大宽度。
        imgHeigth.value = newImgHeight * kuangDubi + "px"; //高度按宽高比缩放。
    } else {
        imgHeigth.value = newImgHeight * gaoDubi + "px"; //限制高度为最大高度。
        imgWidth.value = newImgWidth * gaoDubi + "px"; //宽度按宽高比缩放。
    }
}

// 获取选中的颜色，并转RGB结构体
function getSelectRGB(value: string) {
    // 选中透明色则返回undefined
    if (value == "touming") {
        imgBase.color = undefined;
        return;
    }
    // 分割字符串转结构体
    let a = {} as BGRA;
    let rgbList = value.substring(4, value.length - 1).split(",");
    if (rgbList?.length == 3) {
        a.r = Number(rgbList[0]);
        a.g = Number(rgbList[1]);
        a.b = Number(rgbList[2]);
    }
    imgBase.color = a;
    colorChange.value = true
}
// 界面上展示的颜色列表，最后一个对应自定义颜色
const colorList = ref(["rgb(255,0,0)", "rgb(129,207,255)", "rgb(34,135,244)", "rgb(255,255,255)", "rgb(255,0,0)"]);

// 选择自定义颜色的调用
const customColorPick = (e: any) => {
    colorList.value[colorList.value.length - 1] = hexToRgb(e.target.value);
    // 将其至于选中项
    let colorLen = document.getElementById("color-" + colorList.value.length);
    if (colorLen) {
        (colorLen as any).checked = true;
    }
    // 判断是否和前面的值相同，如果是，则将前面的值标为选中项
    for (let i = 0; i < colorList.value.length - 1; i++) {
        if (colorList.value[i] == colorList.value[colorList.value.length - 1]) {
            colorLen = document.getElementById("color-" + (i + 1));
            if (colorLen) {
                (colorLen as any).checked = true;
            }
            break;
        }
    }
    getSelectRGB(colorList.value[colorList.value.length - 1])
};
// 打开颜色选择面板
function colorpickShow() {
    document.getElementById("customColor")?.click();
}
// 最后一个自定义颜色是否展示
function colorLastShow() {
    for (let i = 0; i < colorList.value.length - 1; i++) {
        if (colorList.value[i] == colorList.value[colorList.value.length - 1]) {
            return false;
        }
    }
    return true;
}

// 颜色的16进制转rgb字符串
function hexToRgb(hex: string) {
    var r = parseInt(hex.slice(1, 3), 16),
        g = parseInt(hex.slice(3, 5), 16),
        b = parseInt(hex.slice(5, 7), 16);
    return "rgb(" + r + "," + g + "," + b + ")";
}
let maxWidth = 0;
let maxHeight = 0;
// 首次加载时初始化
onMounted(() => {
    maxWidth = document.documentElement.clientWidth * 0.95; // 减去左侧菜单的宽度，减去一定的空间预留
    maxHeight = document.documentElement.clientHeight * 0.8; // 减去一定的空间预留，防止图片过大时，页面被图片撑开。
    getImgSize(439, 439)
});
</script>

<style lang="scss" scoped>
.title::after {
    content: '人像分割 | 证件照换底色';
    position: absolute;
    left: 0;
    color: black;
    transform: translate(24px, 6px) scaleX(0.93) scaleY(0.5) skew(50deg);
    z-index: -1;
    filter: blur(1px);
    mask: linear-gradient(transparent, black);
}

.custom-radios {
    div {
        display: inline-block;
    }

    input[type="radio"] {
        display: none;

        +label {
            color: #333;
            font-family: Arial, sans-serif;
            font-size: 14px;

            span {
                display: inline-block;
                width: 30px;
                height: 30px;
                margin: -1px 4px 0 0;
                vertical-align: middle;
                cursor: pointer;
                border-radius: 50%;
                box-shadow: inset 0px 0px 0px 2px rgba(0, 0, 0, 0.33);
                background-repeat: no-repeat;
                background-position: center;
                text-align: center;
                line-height: 44px;
            }
        }

        &:checked+label span {
            width: 50px;
            height: 50px;
        }
    }
}

.color-pick {
    display: inline-block;
    width: 30px;
    height: 30px;
    margin: -1px 4px 0 0;
    vertical-align: middle;
    cursor: pointer;
    border-radius: 50%;
    box-shadow: inset 0px 0px 0px 2px rgba(0, 0, 0, 0.33);
    background-repeat: no-repeat;
    background-position: center;
    text-align: center;
    line-height: 44px;
}

.touming {
    background-color: white;
    background-image: repeating-conic-gradient(#eee 0 25%, transparent 0 50%);
    background-size: 32px 32px;
    height: 100%;
    width: 100%;
}
</style>
